#include "class.Node.h"
#include "class.LinearAdapter.h"

#include <iostream>
#include <string>
#include <cstdlib>

#include <stdio.h>
#include <termios.h>
#include <unistd.h>

#define ESC "exit"

using namespace std;

bool printMenu();
bool handleMsg(string choice);
bool CreateList();
bool QueryNode();
bool InsertNode();
bool DeleteNode();
bool FetchAll();
bool SortNodes();
void goBack();
bool checkList();

LinearAdapter* adapter;

int main(int argc, char** args)
{
    string CHOICE = "";
    while(CHOICE != ESC)
    {
        system("clear");
        printMenu();
        cin >> CHOICE;
        cin.clear();
        bool result = handleMsg(CHOICE);
        if(result)
        {
            cout << "Operation Success" << endl;
        }else{
            break;
        }
    }
    return 0;
}

bool checkList()
{
    if(adapter == NULL)
    {
        cout << "ERROR: There is no LinkList exists, please create one first." << endl;        
        return false;
    }
    else return true;
}

bool printMenu()
{
    cout << "-----------------------" << endl;
    cout << endl;
    cout << "1. Create link list." << endl;
    cout << "2. Query node by id." << endl;
    cout << "3. Insert node." << endl;
    cout << "4. Delete node." << endl;
    cout << "5. Fetch all nodes." << endl;
    cout << "6. Sort nodes." << endl;
    cout << "7. Exit." << endl;
    cout << endl;
    cout << "-----------------------" << endl;
    cout << "Please type in your choice: ";
}

bool handleMsg(string choice)
{
    if(choice == "1")
    {
        return CreateList();
    }else if(choice == "2"){
        return QueryNode();
    }else if(choice == "3"){
        return InsertNode();
    }else if(choice == "4"){
        return DeleteNode();
    }else if(choice == "5"){
        return FetchAll();
    }else if(choice == "6"){
        return SortNodes();
    }else if(choice == "7"){
        return false;
    }else{
        return true;
    }
}

bool CreateList()
{
    if(adapter != NULL)delete adapter;
    adapter = new LinearAdapter();
    cout << "Input the length:";
    int length = 0;
    cin >> length;
    cin.clear();
    string content;
    for(int i=0; i<length; i++)
    {
        cout << "Input value[" << i+1 << "]:";
        cin >> content;
        Node* node = new Node(content);
        adapter->append(node);
    }
    return true;
}

bool QueryNode()
{
    int index = 0;
    if(!checkList())
    {
        return true;
    }
    cout << "Input the index of the node [0-" << adapter->getLength()-1 <<"]:" ;
    cin >> index;
    while(index > adapter->getLength()-1 || index < 0)
    {
        cout << "Sorry, index is out of range.[0-" 
            << adapter->getLength()-1 << "]" << endl;
        cin >> index;
    }
    Node* node = adapter->get(index);
    cout << "Query Success!" << endl;
    cout << "[" << index << "]";
    cout << node->getContent() << endl;
    goBack();
    return true;
}

bool InsertNode()
{
    if(!checkList())
    {
        return true;
    }
    int pos = 0;
    string body = "";
    cout << "Please input the postion you want to insert:";
    cin >> pos;
    cin.clear();
    while(pos > adapter->getLength()-1 || pos < 0)
    {
        cout << "Out of range, please enter again:";
        cin >> pos;
        cin.clear();
    }
    cout << "Please type in the value:";
    cin >> body;
    cin.clear();
    Node* node = new Node(body);
    adapter->insert(node, pos);
    goBack();
    return true;
}

bool DeleteNode()
{
    if(!checkList())
    {
        return true;
    }
    int pos = 0;
    cout << "Please input the index of the node you want to delete[0-" 
        << adapter->getLength()-1 << "]:";
    cin >> pos;
    cin.clear();
    if(pos < 0 || pos > adapter->getLength()-1)
    {
        cout << "Out of range.";
        return true;
    }
    if(!adapter->remove(pos))
    {
        cout << "Delete fail." << endl;
    }
    return true;
}

bool FetchAll()
{
    if(!checkList())
    {
        return true;
    }
    int length = adapter->getLength();
    cout << (length) << " items in all:" << endl;
    Node* node;
    for(int i=0; i<length; i++)
    {
        node = adapter->get(i);
        cout << "[" << (i+1) << "] " << node->getContent() << endl;
    }
    goBack();
    return true;
}

bool SortNodes()
{
    if(!checkList())
    {
        return true;
    }
    adapter->sort();
    goBack();
    return true;
}

void goBack()
{
    string tmp;
    cout << "Press [ENTER] to go back main menu...";
    cin >> tmp;
    cin.clear();
    return;
}